class BaseSymbol {
  type: string;
  value: any;
  /**
   * 设定类型和值
   * @param type 类型
   * @param value 值
   */
  constructor(type: string, value: any) {
    this.type = type;
    this.value = value;
  }
}
class IntegerSymbol extends BaseSymbol {
  value: number;
  /**
   * 设定数字值
   * @param value 数字
   */
  constructor(value = 0) {
    super("Integer", value);
  }
}
class RealSymbol extends BaseSymbol {
  value: number;
  /**
   * 设定数字值
   * @param value 数字
   */
  constructor(value = 0) {
    super("Real", value);
  }
}
class StringSymbol extends BaseSymbol {
  value: string;
  /**
   * 设定字符串值
   * @param value 字符串
   */
  constructor(value = "") {
    super("String", value);
  }
}
class VectorSymbol extends BaseSymbol {
  value: [];
  /**
   * 设定自定义类型初始值
   * @param value 自定义类型的值
   * @param vectorType 自定义类型名
   */
  constructor(value = [], vectorType = "Vector") {
    super(vectorType, value);
  }
}
class FunctionArgument {
  name: string;
  type: string;
  /**
   * 设定函数参数初始值
   * @param name 参数名
   * @param type 参数类型
   */
  constructor(name: string, type: string) {
    this.name = name;
    this.type = type;
  }
}
class FunctionSymbol extends BaseSymbol {
  value: Function;
  params: FunctionArgument[];
  returnType: string;
  /**
   * 设定函数符号初始值
   * @param value 函数体
   * @param returnType 返回类型
   * @param params 参数列表
   */
  constructor(
    value: Function,
    returnType: string,
    params: FunctionArgument[] = []
  ) {
    super("Function", value);
    this.params = params;
    this.returnType = returnType;
  }
}
class ProcedureSymbol extends BaseSymbol {
  /**
   * 设定过程符号初始值
   * @param value 过程体
   */
  constructor(value) {
    super("Procedure", value);
  }
}
const SymbolMap: { [name: string]: { new (...args: any[]): BaseSymbol } } = {
  Integer: IntegerSymbol,
  Real: RealSymbol,
  String: StringSymbol,
};
/**
 * 根据类型名创建类型的工厂函数
 * @param typeName 类型名
 */
function Create(typeName: string): BaseSymbol {
  if (typeName in SymbolMap) {
    return new SymbolMap[typeName]();
  }
  return new VectorSymbol([], typeName);
}
export {
  Create,
  BaseSymbol,
  IntegerSymbol,
  RealSymbol,
  StringSymbol,
  VectorSymbol,
  FunctionSymbol,
  FunctionArgument,
  ProcedureSymbol,
};
